﻿/// <reference path="../../utilities/FXDom.js" />
/// <reference path="../../utilities/Color.js" />
/// <reference path="../../utilities/Post.js" />
/// <reference path="../../utilities/Xpcom.js" />
///--------------------------------------------------------------------
/// <file name="MarkupStripper.js">
///   Strips markup from posts.
/// </file>
///--------------------------------------------------------------------

NAMFox.ns(function() { with (NAMFox) {

this.MarkupStripper = function(elementSelector, htmlDocument) {
    /// <summary>
    /// Initializes a new instance of the MarkupStripper class.
    /// </summary>
    /// <param name="elementSelector" type="MarkupElementSelector">
    /// The element selector that finds the elements whose markup must be stripped.
    /// </param>
    
    this._elementSelector = elementSelector;
};

MarkupStripper.colorExpr = /rgb\((\d+), (\d+), (\d+)\)/;
MarkupStripper.editTagExpr = /This message was edited by [\s\w\(\)]+ on \w+ \d+ \d+\.(?:$|<\/font>$|<\/span>$)/;

MarkupStripper.prototype = {
    _colorMap: {
        aqua: Color.fromRgb(0, 255, 255),
        black: Color.fromRgb(0, 0, 0),
        blue: Color.fromRgb(0, 0, 255),
        brown: Color.fromRgb(165, 42, 42),
        fuchsia: Color.fromRgb(255, 0, 255),
        gray: Color.fromRgb(128, 128, 128),
        green: Color.fromRgb(0, 128, 0),
        lime: Color.fromRgb(0, 255, 0),
        maroon: Color.fromRgb(128, 0, 0),
        navy: Color.fromRgb(0, 0, 128),
        olive: Color.fromRgb(128, 128, 0),
        orange: Color.fromRgb(255, 165, 0),
        purple: Color.fromRgb(128, 0, 128),
        red: Color.fromRgb(255, 0, 0),
        silver: Color.fromRgb(192, 192, 192),
        teal: Color.fromRgb(0, 128, 128),
        white: Color.fromRgb(255, 255, 255),
        yellow: Color.fromRgb(255, 255, 0)
    },
    
    _normalizeSize: function(postContainer, markupTag) {
        /// <summary>
        /// Normalizes the size on any markup tag.
        /// </summary>
        /// <param name="postContainer" type="FXDom">
        /// The DOM element that contains the post content, represented as an FXDom object.
        /// </param>
        /// <param name="markupTag" type="String">
        /// The HTML tag to normalize the size of.
        /// </param>
        
        postContainer.find(markupTag).css("fontSize", "inherit");
    },
    
    _replaceColor: function(postContainer) {
        /// <summary>
        /// Replaces colored text with black text.
        /// </summary>
        /// <param name="postContainer" type="FXDom">
        /// The DOM element that contains the post content, represented as an FXDom object.
        /// </param>
        
        var lightnessThreshold = ($.getConfig().stripMarkup.colorLightness / 100) * 255;
        var that = this;
        postContainer.find("span").each(
            function() {
                if (MarkupStripper.editTagExpr.test(this.innerHTML)) {
                    return;
                }
                
                // Don't strip PHP colors.
                if ($FX.nodeName(this.parentNode, "code")) {
                    return;
                }
                
                if ($FX.nodeName(this.parentNode, "span") && this.parentNode.style.color === "rgb(0, 0, 0)") {
                    return;
                }
                
                var colorStyle = this.style.color;
                
                if (!colorStyle) {
                    return;
                }
                
                var color;
                
                if (that._colorMap.hasOwnProperty(colorStyle)) {
                    color = that._colorMap[colorStyle];
                }
                else {
                    var result = colorStyle.match(MarkupStripper.colorExpr);
                    
                    color = Color.fromRgb(result[1], result[2], result[3]);
                }
                
                $.verbose(
                    "MARKUP STRIP | " + colorStyle + " : Found " + color.lightness +
                    " against " + lightnessThreshold
                );
                
                // Remember we only strip if the lightness is above the threshold,
                // not if it's equal to it.
                if (color.lightness > lightnessThreshold) {
                    var parent = this.parentNode;
                    while (parent && (!$FX.nodeName(parent, "div") || parent.className !== "qt")) {
                        parent = parent.parentNode;
                    }
                    
                    if (parent) {
                        $.verbose("Setting color to #333366 since it is part of a quote.");
                        this.style.color = "#333366";
                    }
                    else {
                        this.style.color = "black";
                    }
                }
            }
        );
    },
    
    _replaceContent: function(postContainer) {
        /// <summary>
        /// Strips markup from the postContent.
        /// </summary>
        /// <param name="postContainer" type="nsIDOMHTMLElement">
        /// The DOM element which contains the post content.
        /// </param>
        /// <returns type="String" />
        
        var stripOptions = $.getConfig().stripMarkup.stripOptions;
        if (!stripOptions) {
            return;
        }
        
        postContainer = $FX(postContainer);
        
        if ((stripOptions & StripOptions.Color) !== 0) {
            this._replaceColor(postContainer);
        }
        
        if ((stripOptions & StripOptions.SizeOne) !== 0) {
            this._replaceSizeOne(postContainer);
        }
        
        if ((stripOptions & StripOptions.Sub) !== 0) {
            this._normalizeSize(postContainer, "sub");
        }
        
        if ((stripOptions & StripOptions.Sup) !== 0) {
            this._normalizeSize(postContainer, "sup");
        }
    },
    
    _replaceSizeOne: function(postContainer) {
        /// <summary>
        /// Replaces size 1 text with size 2 text.
        /// </summary>
        /// <param name="postContainer" type="FXDom">
        /// The DOM element that contains the post content, represented as an FXDom object.
        /// </param>
        
        postContainer.find("font[size=1]").each(
            function() {
                $.verbose("MARKUP STRIP | Considering size=1 with inner content: " + this.innerHTML);
                
                if (MarkupStripper.editTagExpr.test(this.innerHTML)) {
                    return;
                }
                
                // <blockquote> for [quote] tag, <td> for [php] and [code]
                if (!$FX.nodeName(this.parentNode, "blockquote") && !$FX.nodeName(this.parentNode, "td")) {
                    $FX(this).after(this.innerHTML).remove();
                }
            }
        );
    },
    
    attach: function() {
        /// <summary>
        /// Strips markup on all elements on the page.
        /// </summary>
        
        if (!$.getConfig().stripMarkup.stripOptions) {
            return;
        }
        
        var elements = this._elementSelector.getElements();
        for (var i = 0; i < elements.length; ++i) {
            this._replaceContent(elements[i]);
        }
    }
};

}});